본문으로 건너뛰기

IPC에 대해서 설명해주세요.

IPC란 프로세스들 간에 데이터 및 정보를 주고 받기 위한 메커니즘으로, 커널에서 IPC를 위한 도구를 System Call의 형태로 제공한다.

종종 여러 프로세스가 협업할 필요가 있는 경우가 있다. 예를 들어 브라우저는 렌더러 프로세스와 각 플러그인 별 프로세스를 가지는 프로세스이다.

렌더러 프로세스는 HTML/CSS를 읽어 렌더링하고 인터프리터로 JS 코드를 실행해야 한다. 각 역할별 프로그램을 분리하여 모듈화 한 것이다. 이런 실행환경에서는 프로세스 간의 통신이 가능해야한다. 프로세스간 통신은 운영체제의 도움이 필요하다.

  • 프로세스 내부 데이터 통신: 하나의 프로세스 내에 2개 이상의 스레드가 존재하는 경우의 통신이다. 프로세스 내부의 스레드는 전역 변수나 파일을 이용하여 데이터를 주고 받는다.
  • 프로세스 간 데이터 통신: 같은 컴퓨터에 있는 여러 프로세스끼리 통신하는 경우로, 공용 파일 또는 운영체제가 제공하는 파이프를 사용하여 통신한다.
  • 네트워크를 이용한 데이터 통신: 여러 컴퓨터가 네트워크로 연결되어 있을 때도 통신이 가능한데, 이 경우 프로세스는 소켓을 이용하여 데이터를 주고받는다. 이처럼 소켓을 이용하는 프로세스간 통신을 네트워킹이라고 한다. 다른 컴퓨터에 있는 함수를 호출하여 통신하는 원격 프로시저 호출도 여기에 해당한다.

프로세스간 통신의 분류

통신 방향에 따른 분류

통신은 데이터가 전송되는 방향에 따라 양방향 통신(duplex communication), 반양방향 통신(half-duplex communication), 단방향 통신(simplex communication)으로 나뉜다.

  • 양방향 통신: 데이터를 동시에 양쪽 방향으로 전송할 수 있는 구조로, 일반적인 통신은 모두 양방향 통신이다. 프로세스간 통신에서는 소켓 통신이 양방향 통신에 해당한다.
  • 반양방향 통신: 데이터를 양쪽 방향으로 전송할 수 있지만 동시 전송은 불가능하고 특정 시점에 한쪽 방향으로 전송할 수 있는 구조이다. 반양방향 통신의 대표적인 예는 무전기이다.
  • 단방향 통신: 모스 신호처럼 한쪽 방향으로만 데이터를 전송할 수 있는 구조이다. 프로세스 간 통신에서는 전역 변수와 파이프가 단방향 통신에 해당한다.

통신 구현 방식에 따른 분류

전역 변수를 사용하는 통신 방식의 가장 큰 문제는 언제 데이터를 보낼지 데이터를 받는 쪽에서 모른다는 것이다. 그러므로 데이터를 받는 쪽에서는 반복적으로 전역 변수의 값을 점검하는 수밖에 없다. 우편함에 편지가 있는지 수시로 열어보는 것처럼 상태 변화를 살펴보기 위해 반복문을 무한 실행하며 기다리는 것을 바쁜대기(busy waiting)라고 한다. 세스템 차원에서 큰 자원 낭비인 바쁜 대기는 안 좋은 프로그램의 전형적인 예이다.

바쁜 대기 문제를 해결하기 위해서는 데이터가 도착했음을 알려주는 동기화(synchronization)를 사용한다. 동기화를 사용하면 바쁜 대기를 하지 않아도 운영체제가 알아서 알려준다.

프로세스 간 통신은 동기화 기느잉 있느냐 없느냐에 따라 대기가 있는 통신(blocking communication)과 대기가 없는 통신(non-blocking communication)으로 구분된다. 대기가 있는 통신은 동기화 통신, 대기가 없는 통신은 비동기화 통신이라고도 한다.

  • 대기가 있는 통신: 동기화를 지원하는 통신 방식이다. 데이터를 받는 쪽은 데이터가 도착할 때까지 자동으로 대기 상태에 머물러 있다.
  • 대기가 없는 통신: 동기화를 지원하지 않는 통신 방식이다. 데이터를 받는 쪽은 바쁜 대기를 사용하여 데이터가 도착했는지 여부를 직접 확인한다.
분류 방식종류
통신 방향에 따른 분류양방향 통신일반적 통신, 소켓
반양방향 통신무전기
단방향 통신전역 변수, 파일, 파이프
통신 방향에 따른 분류대기가 있는 통신(동기화 통신)파이프, 소켓
대기가 없는 통신(비동기화 통신)전역 변수, 파일

프로세스 간 통신의 종류

전역 변수를 이용한 통신

전역 변수를 이용한 통신은 공동으로 관리하는 메모리를 사용하여 데이터를 주고받는 것이다. 데이터를 보내는 쪽에서는 전역 변수나 파일에 값을 쓰고, 데이터를 받는 쪽에서는 전역 변수의 값을 읽는다. 전역 변수를 이용한 통신 방식은 주로 직접적으로 관련이 있는 프로세스간에 사용한다. 예를 들어 부모 프로세스가 전역 변수를 선언한 후 자식 프로세스를 만들면 부모 프로세스와 자식 프로세스가 통신을 할 수 있다.

파일을 이용한 통신

파일은 열기(open), 쓰기(write), 읽기(read), 닫기(close)의 4가지로 구성된다.

int main(){
    int fd;
    char buf[5];

    fd = open('com.txt', O_RDWR);
    write(fd, "test", 5);
    read(fd, buf, 5);
    close(fd);
}
  1. open하여 fd(파일 디스크립터)를 받아 이를 통해 파일을 제거한다. fd는 반드시 사용 후에 돌려주어야 하기 때문에 close를 호출해주어야 한다.
  2. 그 다음 쓰기, 읽기로 fd를 사용하여 파일의 정보를 쓰고, fd에 buf에 저장된 정보를 읽어온다.

입출력은 위와 같이 입출력 프로세스가 따로 존재한다. 그렇다면 운영체제 입장에서 보면 저장장치의 데이터를 읽고 쓰는 것도 일반 프로세스와 입출력 프로세스 간의 통신이다.

파일을 이용한 통신은 부모-자식 관계 프로세스 간 통신에 많이 사용되며 운영체제가 프로세스 동기화를 제공하지 않는다. 그래서 프로세스가 알아서 동기화를 해야하는데 주로 부모 프로세스가 wait() 함수를 이용해서 자식 프로세스의 작업이 끝날 때까지 기다렸다가 작업을 시작한다.

파이프를 이용한 통신

프로세스 동기화 문제를 해결하는 방법으로 파이프가 있다. 파이프는 운영체제가 제공하는 동기화 통신 방식으로, 파일 입출력과 같이 open() 함수로 기술자를 얻고 작업을 한 후 close() 함수로 마무리한다. 파이프를 이용한 통신은 전역 변수를 이용한 통신과 마찬가지로 단방향 통신이다. 파이프로 양방향 통신을 하려면 파이프 2개를 사용해야 한다.

위 그림은 2개의 파이프를 이용한 통신을 나타낸 것이다. 파이프에 쓰기 연산을 하면 데이터가 전송되고 읽기 연산을 하면 데이터를 받는다. 만약 프로세스 B가 파이프 1에 대해 읽기 연산을 수행했는데 파이프 1이 쓰기 연산을 하지 않았다면 프로세스 B는 대기 상태가 된다. 이러한 대기 상태는 프로세스 A가 파이프 1에 데이터를 쓰는 순간 자동으로 풀려 동기화가 이루어진. 프로세스 B는 바쁜 대기를 하지 않아도 된다.

파이프는 이름 없는 파이프와 이름있는 파이프로 나뉜다.

  • 이름 없는 파이프(anonymous pipe): 일반적으로 파이프라고하면 이름없는 파이프를 가리킨다. 부모와 자식 프로세스 혹은 같은 부모를 가진 자식 프로세스와 같이 서로 관련 있는 프로세스 간 통신에 사용된다.
  • 이름 있는 파이프: FIFO라 불리는 특수 파일을 이용하여 서로 관련 없는 프로세스 간 통신에 사용된다.

소켓을 이용한 통신

여러 컴퓨터에 있는 프로세스끼리도 통신을 할 수 있다. 여러 컴퓨터에 있는 프로세스 간 통신을 네트워킹이라고 한다. 네트워킹 상황에서의 통신은 원격 프로시저 호출이나 소켓을 이용한다. 프로시저 호출이 한 컴퓨터에 있는 함수를 호출하는 것이라면, 원격 프로시저 호출은 다른 컴퓨터에 있는 함수를 호출하는 것이다.

일반적으로 원격 프로시저 호출은 소켓을 이용하여 구현한다. 다른 컴퓨터에 있는 프로세스와 통신을 하려면 그 컴퓨터의 위치를 파악하고, 원격지의 시스템 내 여러 프로세스 중 어떤 프로세스와 통신을 할지도 결정해야 한다. 이때 통신하고자 하는 프로세스는 소켓에 쓰기 연산을 하면 데이터가 전송되고, 읽기 연산을 하면 데이터를 받게된다.

소켓은 동기화를 지원하므로 데이터를 받는 쪽의 프로세스가 바쁜대기를 하지 않아도 된다. 양방향 통신을 하기 위해 파이프는 2개를 사용했지만 소켓은 하나만 사용해도 양방향 통신이 가능하다.

Reference

  • 쉽게 배우는 운영체제